#include <iostream>
#include <string>
#include <cassert>
#include <unistd.h>
#include <pthread.h>

#define THREAD_NUM 4

bool quit = false;

// 可以使用全局的互斥锁mutex和条件变量cond
pthread_cond_t g_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;

typedef void (*func_t)(const std::string& name, pthread_mutex_t *pmtx, pthread_cond_t *pcont);

struct threadData
{
    std::string _name;
    pthread_mutex_t *_pmtx;
    pthread_cond_t *_pcont;
    func_t _func;   

    // 构造函数
    threadData(const std::string& name, pthread_mutex_t *pmtx, pthread_cond_t *pcont, func_t func)
        : _name(name), _pmtx(pmtx), _pcont(pcont), _func(func)
    { }
};

void func1(const std::string& name, pthread_mutex_t *pmtx, pthread_cond_t *pcont)
{
    while(!quit)
    {
        pthread_mutex_lock(pmtx);
        pthread_cond_wait(pcont, pmtx);
        if(!quit) std::cout << name << " ----- a" << std::endl;
        pthread_mutex_unlock(pmtx);
    }
} 

void func2(const std::string& name, pthread_mutex_t *pmtx, pthread_cond_t *pcont)
{
    while(!quit)
    {
        pthread_mutex_lock(pmtx);
        pthread_cond_wait(pcont, pmtx);
        if(!quit) std::cout << name << " ----- b" << std::endl;
        pthread_mutex_unlock(pmtx);
    }
} 

void func3(const std::string& name, pthread_mutex_t *pmtx, pthread_cond_t *pcont)
{
    while(!quit)
    {
        pthread_mutex_lock(pmtx);
        pthread_cond_wait(pcont, pmtx);
        if(!quit) std::cout << name << " ----- c" << std::endl;
        pthread_mutex_unlock(pmtx);
    }
} 

void func4(const std::string& name, pthread_mutex_t *pmtx, pthread_cond_t *pcont)
{
    while(!quit)
    {
        pthread_mutex_lock(pmtx);
        pthread_cond_wait(pcont, pmtx);
        if(!quit) std::cout << name << " ----- d" << std::endl;
        pthread_mutex_unlock(pmtx);
    }
} 

void *Entry(void *args)
{
    threadData *pth = (threadData*)args;
    // 传参，调用函数
    pth->_func(pth->_name, pth->_pmtx, pth->_pcont);
    return nullptr;
}

int main()
{
    // 创建线程
    pthread_t tid[THREAD_NUM];

    // 创建线程锁和条件变量
    pthread_mutex_t mutex;
    pthread_cond_t cond;

    pthread_mutex_init(&mutex, nullptr);
    pthread_cond_init(&cond, nullptr);

    // 每个线程调用的函数指针
    func_t func[THREAD_NUM] = { func1, func2, func3, func4 };  

    for(int i = 0; i < THREAD_NUM; ++i)
    {
        // 创建线程
        std::string name = "thread ";
        name += std::to_string(i + 1);
        threadData *pth = new threadData(name, &mutex, &cond, func[i]);
        int n = pthread_create(tid + i, nullptr, Entry, (void*)pth);
        assert(n == 0);
    }

    sleep(1);

    // 主线程控制子线程
    int count = 5;
    while(count)
    {
        std::cout << "Thread Control " << count-- << std::endl;
        int n = pthread_cond_signal(&cond);
        // int n = pthread_cond_broadcast(&cond);
        assert(n == 0);
        sleep(1);
    }

    sleep(1);

    std::cout << "Control Over" << std::endl;
    quit = true;
    pthread_cond_broadcast(&cond);

    // 主线程等待子线程
    for(int i = 0; i < THREAD_NUM; ++i)
    {
        int n = pthread_join(tid[i], nullptr);
        assert(n == 0);
        std::cout << "wait " << tid[i] << " successful" << std::endl;
    }

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}